#include "format.h"

#include <limits>
#include <cstdint>
#include <string>
#include <stdexcept>

namespace simple::musical
{

	bool is_float(format f) noexcept
	{
		const auto sdlf = static_cast<SDL_AudioFormat>(f);
		return SDL_AUDIO_ISFLOAT(sdlf);
	}

	bool is_big_endian(format f) noexcept
	{
		const auto sdlf = static_cast<SDL_AudioFormat>(f);
		return SDL_AUDIO_ISBIGENDIAN(sdlf);
	}

	bool is_signed(format f) noexcept
	{
		const auto sdlf = static_cast<SDL_AudioFormat>(f);
		return SDL_AUDIO_ISSIGNED(sdlf);
	}

	int bit_size(format f) noexcept
	{
		const auto sdlf = static_cast<SDL_AudioFormat>(f);
		return SDL_AUDIO_BITSIZE(sdlf);
	}

	int byte_size(format f) noexcept
	{
		return bit_size(f) / std::numeric_limits<std::uint8_t>().digits;
	}

	const char* to_c_str(format fmt)
	{
		if(format::int8 == fmt) return "int8";
		if(format::uint8 == fmt) return "uint8";
		if(format::int16_lsb == fmt) return "int16_lsb";
		if(format::int16_msb == fmt) return "int16_msb";
		// if(format::int16_sys == fmt) return "int16_sys"; // alias
		// if(format::int16 == fmt) return "int16"; // alias
		if(format::uint16_lsb == fmt) return "uint16_lsb";
		if(format::uint16_msb == fmt) return "uint16_msb";
		// if(format::uint16_sys == fmt) return "uint16_sys"; // alias
		// if(format::uint16 == fmt) return "uint16"; // alias
		if(format::int32_lsb == fmt) return "int32_lsb";
		if(format::int32_msb == fmt) return "int32_msb";
		// if(format::int32_sys == fmt) return "int32_sys"; // alias
		// if(format::int32 == fmt) return "int32"; // alias
		if(format::float32_lsb == fmt) return "float32_lsb";
		if(format::float32_msb == fmt) return "float32_msb";
		// if(format::float32_sys == fmt) return "float32_sys"; // alias
		// if(format::float32 == fmt) return "float32"; // alias

		throw std::runtime_error("Invalid audio sample format!");
	}

	format format_from_c_str(const char* str)
	{
		using namespace std::literals;
		if(str == "int8"s) return format::int8;
		if(str == "uint8"s) return format::uint8;
		if(str == "int16_lsb"s) return format::int16_lsb;
		if(str == "int16_msb"s) return format::int16_msb;
		if(str == "int16_sys"s) return format::int16_sys;
		if(str == "int16"s) return format::int16;
		if(str == "uint16_lsb"s) return format::uint16_lsb;
		if(str == "uint16_msb"s) return format::uint16_msb;
		if(str == "uint16_sys"s) return format::uint16_sys;
		if(str == "uint16"s) return format::uint16;
		if(str == "int32_lsb"s) return format::int32_lsb;
		if(str == "int32_msb"s) return format::int32_msb;
		if(str == "int32_sys"s) return format::int32_sys;
		if(str == "int32"s) return format::int32;
		if(str == "float32_lsb"s) return format::float32_lsb;
		if(str == "float32_msb"s) return format::float32_msb;
		if(str == "float32_sys"s) return format::float32_sys;
		if(str == "float32"s) return format::float32;

		throw std::runtime_error("Invalid audio sample format!");
	}

} // namespace simple::musical
